home *** CD-ROM | disk | FTP | other *** search
- /* Internet LPD Server
- * written by David Johnson (dave@cs.olemiss.edu)
- *
- * This code is in the public domain.
- *
- * Revision History:
- *
- * Revision 1.5 91/09/28 dave
- * Separate filenames in lpq -l with commas
- * Log permission rejections to the queue error log file
- *
- * Revision 1.4 91/09/26 dave (from Hans-Juergen Knobloch)
- * Reset secure flag on startup so the security features may be enabled
- * and disabled without leaving net
- * Changed definition of priority to char
- * Changed definition of job size in send_queue() to a long
- * Changed formatting of date in send_queue()
- *
- * Revision 1.3 91/09/19 dave
- * Had to update is_job_specified() since additional letter sequence
- *
- * Revision 1.2 91/09/17 dave
- * Job number reported to lpq included part which was not numeric
- * Long hostname in send_queue() would overflow line buffer
- * Date in send_queue() was not terminated properly
- *
- * Revision 1.1 91/09/14 dave
- * Finished permission checking
- *
- * Revision 1.0 91/09/04 dave
- * Initial Release
- *
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <time.h>
- #include <sys/stat.h>
- #ifdef __TURBOC__
- #include <io.h>
- #include <dir.h>
- #endif
- #include "global.h"
- #include "mbuf.h"
- #include "proc.h"
- #include "iface.h"
- #include "usock.h"
- #include "socket.h"
- #include "domain.h"
- #include "dirutil.h"
- #include "commands.h"
- #include "files.h"
- #include "lp.h"
- #include "lpd.h"
-
- /* in lpdunsp.c */
- extern void start_all_unspoolers __ARGS((int s, void *unused, void *p));
- extern void start_unspooler __ARGS((char *queue));
-
- /* in lpdsubr.c */
- extern void free_queue_status __ARGS((void));
- extern int get_job_list __ARGS((char *directory, struct job_entry **job_list));
- extern int get_new_sequence_no __ARGS((struct LPDtrans *LPD));
- extern int init_queue_status __ARGS((void));
- extern int is_unspooler_active __ARGS((char *queue, char **job));
- extern int kill_unspooler __ARGS((char *queue));
- extern void lpd_log __ARGS((struct LPDtrans *LPD, char *message, ...));
- extern char *read_printcap __ARGS((struct LPDtrans *LPD, char *queue));
- extern int read_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq, char **message));
-
- /* local functions - public */
- char *extract_parms __ARGS((char *local_parms, int extra));
- int is_job_specified __ARGS((char *cf_name));
- int is_lpd_active __ARGS((void));
- int lpd0 __ARGS((int argc, char *argv[], void *p));
- int lpdstart __ARGS((int argc, char *argv[], void *p));
- int trunc_strcat __ARGS((char *dest, char *source, int max_length));
-
- /* local functions - private */
- static int check_printer __ARGS((struct LPDtrans *LPD, char *printer_name));
- static void cleanup __ARGS((char *spool_dir, char *filespec));
- static int enter_translation __ARGS((struct LPDxlat *xlat_table, char *filename,
- char *remotefile));
- static int fixup_and_write_control_file __ARGS((struct LPDtrans *LPD, char *filename));
- static int get_owner __ARGS((char *directory, char *cf_name, char **owner));
- static void lpd __ARGS((int s, void *unused, void *p));
- static int receive_control_file __ARGS((struct LPDtrans *LPD,
- unsigned long filesize, int s));
- static int receive_data_file __ARGS((char *filename,
- unsigned long filesize, int s));
- static int receive_job __ARGS((struct LPDtrans *LPD));
- static int remove_files __ARGS((char *directory, char *cf_name));
- static int remove_job __ARGS((struct LPDtrans *LPD, char *local_parms));
- static int send_queue __ARGS((struct LPDtrans *LPD, int type, char *local_parms));
- static int validate_control_file __ARGS((struct LPDtrans *LPD, char *priority));
-
-
- static int Slpd = -1; /* Prototype socket for service */
-
- int secure = 0; /* default to non-secure */
-
-
- /* Start up LPD service */
- int
- lpdstart(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct sockaddr_in lsocket;
- struct sockaddr_in from_addr;
- int c, s, from_len;
-
- if( Slpd != -1 ) {
- /* Already running! */
- return 0;
- }
- secure = 0;
-
- optind = 1; /* reinit getopt() */
- loop: while((c = getopt(argc,argv,"s")) != EOF){
- switch( c ) {
- case 's': /* secure */
- secure = 1;
- break;
- }
- }
-
- psignal( Curproc, 0 ); /* Don't keep the parser waiting */
- chname( Curproc, "LPD listener" );
-
- init_queue_status();
-
- /*
- * Print any entries remaining
- */
- newproc( "LPDstartup", 2048, start_all_unspoolers, 0, NULL, NULL, 0 );
-
- /*
- * Wait for incoming jobs
- */
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- if( optind < argc )
- lsocket.sin_port = atoi( argv[optind]);
- else
- lsocket.sin_port = IPPORT_LPD;
-
- Slpd = socket( AF_INET, SOCK_STREAM, 0 );
- bind( Slpd, (char *)&lsocket, sizeof(lsocket) );
- listen( Slpd, 1 );
- for( ;; ) {
- if( (s = accept( Slpd, (char *)&from_addr, &from_len )) == -1 )
- break; /* Service is shutting down */
-
- if( availmem() < Memthresh ) {
- RESPOND_ERR( s );
- usprintf( s, "server low on memory\n" );
- shutdown( s, 1 );
- } else {
- #ifdef notdef
- if( from_addr.sin_port > 1023 ) {
- /* not allowed */
- close_s( s );
- continue;
- }
- #endif
- /* Spawn a server */
- newproc( "LPDserv", 4096, lpd, s, NULL, NULL, 0 );
- }
- }
- return 0;
- }
-
- static void
- lpd(s,unused,p)
- int s; /* Socket with user connection */
- void *unused;
- void *p;
- {
- struct LPDtrans LPD;
- char buf[512], printer[64], *remote_host, *sp, *dp;
- int cnt = MAXSOCKSIZE;
- union sp sockp;
- char sc[MAXSOCKSIZE];
- struct sockaddr_in from_addr;
-
- memset( (char *)&LPD, 0, sizeof(LPD) ); /* Start with clear slate */
-
- sockowner( s, Curproc ); /* We own it now */
- sockmode( s, SOCK_BINARY );
- LPD.remote = s;
-
- log( s,"open LPD" );
- remote_host = NULL;
- /*
- * Obtain the "domain name" of the remote host to check permissions
- */
- getpeername( s, sc, &cnt );
- sockp.p = sc;
- #ifdef LPD_DEBUG
- tprintf( "secure %d from %s\n", secure, psocket(sc) );
- #endif
- remote_host = resolve_a( sockp.in->sin_addr.s_addr, 0 );
- if( *(remote_host + strlen(remote_host) - 1) == '.' )
- *(remote_host + strlen(remote_host) - 1) = NULL;
- #ifdef LPD_DEBUG
- tprintf( "remote host = %s\n", remote_host );
- tflush();
- #endif
-
- loop: if( (cnt = recvline( s, buf, sizeof(buf) )) == -1){
- /* He closed on us */
- goto finish;
- }
- if( cnt == 0 ){
- /* Can't be a legal LPD command */
- RESPOND_ERR( LPD.remote );
- goto loop;
- }
- rip( buf );
- for( sp = buf+1, dp = printer; *sp && *sp != ' '; *dp++ = *sp++ )
- ;
- *dp = NULL;
- #ifdef LPD_DEBUG
- tprintf( "LPD: request %d - %s\n", *buf, buf+1 );
- #endif
- if( START_CMD <= *buf && *buf <= REMOVE_CMD ) {
- LPD.pc = NULL;
- if( (LPD.name = read_printcap( &LPD, printer )) == NULL ) {
- RESPOND_ERR( LPD.remote );
- usprintf( LPD.remote, "Printer %s (%s) not found.\n", printer, Hostname );
- goto finish;
- }
- }
- if( secure && !check_permission( remote_host, NULL, LPD.name, NULL ) ) {
- RESPOND_ERR( LPD.remote );
- usprintf( LPD.remote, "Your host is not authorized to use %s.\n", buf+1 );
- /*
- * Setup log file
- */
- LPD.logfp = fopen( LPD.pc->LF, "a" );
- lpd_log( &LPD, "lpd: permission rejected for %s, %s, %s, %c ", remote_host, NULL, LPD.name, NULL );
- if( LPD.logfp )
- fclose( LPD.logfp );
- goto finish;
- }
- switch( *buf ) {
- case START_CMD: /* Check queue and print */
- /*
- * Line format: \1printer\n
- */
- RESPOND_OK( LPD.remote );
- close_s( s ); /* close connection */
- start_unspooler( LPD.name );
- break;
- case RECEIVE_CMD: /* Submit a print job */
- /*
- * Line format: \2printer\n
- */
- receive_job( &LPD );
- break;
- case SQUEUE_CMD: /* Display Queue (short form) */
- /*
- * Line format: \3printer [users ...] [jobs ...]\n
- */
- send_queue( &LPD, SQUEUE_CMD, buf+1 );
- break;
- case QUEUE_CMD: /* Display Queue (long form) */
- /*
- * Line format: \4printer [users ...] [jobs ...]\n
- */
- send_queue( &LPD, QUEUE_CMD, buf+1 );
- break;
- case REMOVE_CMD: /* Remove a job from Queue */
- /*
- * Line format: \5printer person [users ...] [job ...]\n
- */
- remove_job( &LPD, buf+1 );
- break;
- default: /* Invalid command */
- RESPOND_ERR( LPD.remote );
- usprintf( LPD.remote, "Invalid command\n" );
- }
- finish:
- log( LPD.remote,"close LPD" );
-
- /* Clean up */
- close_s( LPD.remote );
- if( LPD.pc )
- free( LPD.pc );
- if( LPD.name )
- free( LPD.name );
- if( remote_host )
- free( remote_host );
- }
-
- /* Shut down LPD server */
- int
- lpd0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Slpd);
- Slpd = -1;
- free_queue_status();
-
- return 0;
- }
-
- static int
- receive_job( LPD )
- struct LPDtrans *LPD;
- {
- char *strdup(), priority;
- int cnt, sequence;
- unsigned long filesize;
- char buffer[512], newfilename[13], *path, *remotefile, *strchr();
- FILE *fp;
-
- sequence = get_new_sequence_no( LPD );
- sprintf( newfilename, "xfAA%03d", sequence );
-
- LPD->xlat_table = (struct LPDxlat *)callocw( 1, sizeof( struct LPDxlat ) );
-
- #ifdef LPD_DEBUG
- tprintf( "receive_job( %s )\n", newfilename );
- tflush();
- #endif
-
- RESPOND_OK( LPD->remote );
-
- for( ;; ) {
- if( (cnt = recvline( LPD->remote, buffer, sizeof(buffer) )) == -1 ){
- /* He closed on us */
- break;
- }
- if( cnt == 0 ){
- /* Can't be a legal LPD command */
- RESPOND_ERR( LPD->remote );
- continue;
- }
- rip(buffer);
- #ifdef LPD_DEBUG
- tprintf( "subcommand %d+%s\n", *buffer, buffer+1 );
- tflush();
- #endif
- switch( *buffer ) {
- case ABORT_SCMD: /* flush current files */
- cleanup( LPD->pc->SD, newfilename );
- break;
- case RECEIVE_CF_SCMD: /* control file */
- filesize = atol( buffer+1 );
-
- if( receive_control_file( LPD, filesize, LPD->remote ) < 0 ) {
- tprintf( "could not receive control file\n" );
- cleanup( LPD->pc->SD, newfilename );
- return -1;
- }
- if( validate_control_file( LPD, &priority ) < 0 ) {
- RESPOND_ERR( LPD->remote );
- cleanup( LPD->pc->SD, newfilename );
- return -1;
- } else {
- RESPOND_OK( LPD->remote );
- }
- /*
- * Write out control file
- */
- newfilename[0] = 'c'; /* control file */
- newfilename[2] = priority;
- newfilename[3] = 'A';
- path = pathname( LPD->pc->SD, newfilename );
- fixup_and_write_control_file( LPD, path );
- free( path );
- break;
- case RECEIVE_DF_SCMD:
- filesize = atol( buffer+1 );
- newfilename[0] = 'd'; /* data file */
- path = pathname( LPD->pc->SD, newfilename );
-
- remotefile = strchr( buffer+1, ' ' ) + 1;
-
- if( receive_data_file( path, filesize, LPD->remote ) < 0 ) {
- tprintf( "could not receive %s(%s)\n", remotefile, path );
- cleanup( LPD->pc->SD, newfilename );
- free( path );
- return -1;
- }
- free( path );
- enter_translation( LPD->xlat_table, newfilename, remotefile );
-
- /* increment file letters */
- newfilename[3] = newfilename[3] + 1;
- if( newfilename[3] > 'Z' ) {
- newfilename[3] = 'A';
- newfilename[2] = newfilename[2] + 1;
- }
-
- RESPOND_OK( LPD->remote );
- break;
- }
- }
- free( LPD->xlat_table );
- chname( Curproc, "LPDprint" );
- start_unspooler( strdup( LPD->name ) );
- }
-
- static int
- check_printer( LPD, printer_name )
- struct LPDtrans *LPD;
- char *printer_name;
- {
- char *p1, *p2;
-
- p1 = printer_name;
- p2 = LPD->name;
-
- while( *p1 && *p1 != ' ' )
- *p2++ = *p1++;
- p2 = NULL;
- }
-
- /*
- * cleanup - remove current control and data files
- */
- static void
- cleanup( spool_dir, filespec )
- char *spool_dir, *filespec;
- {
- char *path;
-
- /* remove all data files */
- filespec[0] = 'd';
- do {
- do {
- path = pathname( spool_dir, filespec );
- remove( path );
- free( path );
- } while( filespec[3]-- != 'A' );
- filespec[3] = 'Z';
-
- } while( filespec[2]-- != 'A' );
-
- /* remove control file */
- filespec[0] = 'c';
- filespec[2] = 'A';
- filespec[3] = 'A';
- path = pathname( spool_dir, filespec );
- remove( path );
- free( path );
- }
-
- static int
- receive_data_file( filename, filesize, s )
- char *filename;
- unsigned long filesize;
- int s;
- {
- int bytes, blocksize;
- unsigned long total = 0;
- char *buffer, status;
- FILE *fp;
-
- #ifdef LPD_DEBUG
- tprintf( "receive_data_file( %ld )\n", filesize );
- tflush();
- #endif
-
- fp = fopen( filename, WRITE_BINARY );
-
- filesize++; /* add in status byte */
- blocksize = filesize > BLOCKSIZE ? BLOCKSIZE : filesize;
- buffer = (char *)malloc( blocksize );
-
- RESPOND_OK( s );
- do {
- if( (bytes = recv( s, buffer, blocksize, 0 )) < 1 ) {
- free( buffer );
- fclose( fp );
- return -1;
- }
- if( total + bytes == filesize ) {
- bytes--; /* don't save status byte */
- status = *(buffer + bytes);
- total++;
- }
- if( fwrite( buffer, bytes, 1, fp ) == 0 ) {
- free( buffer );
- fclose( fp );
- return -1;
- }
- total += bytes;
- if( filesize - total < BLOCKSIZE )/* handle last portion */
- blocksize = filesize - total;
- } while( total < filesize );
- free( buffer );
- fclose( fp );
-
- if( status != STATUS_OK ) {
- tprintf( "bad status\n" );
- tflush();
- return -1;
- }
- return 0;
- }
-
- static int
- receive_control_file( LPD, filesize, s )
- struct LPDtrans *LPD;
- unsigned long filesize;
- int s;
- {
- int c, bytes, blocksize;
- unsigned long total = 0;
- char *buffer, status;
-
- #ifdef LPD_DEBUG
- tprintf( "receive_control_file( %ld )\n", filesize );
- tflush();
- #endif
-
- LPD->cf_data = (char *)mallocw( filesize+1 ); /* + NULL byte */
- buffer = LPD->cf_data;
-
- filesize++; /* add in status byte */
- blocksize = filesize > BLOCKSIZE ? BLOCKSIZE : filesize;
-
- RESPOND_OK( s );
- do {
- if( (bytes = recv( s, buffer, blocksize, 0 )) < 1 ) {
- free( LPD->cf_data );
- return -1;
- }
- if( total + bytes == filesize ) {
- bytes--; /* don't save status byte */
- status = *(buffer + bytes);
- total++;
- }
- buffer += bytes;
- total += bytes;
- if( filesize - total < BLOCKSIZE )/* handle last portion */
- blocksize = filesize - total;
- } while( total < filesize );
- LPD->cf_data[ filesize-1 ] = NULL; /* add NULL byte */
-
- if( status != STATUS_OK ) {
- tprintf( "bad status\n" );
- tflush();
- return -1;
- }
- return 0;
- }
-
- static int
- enter_translation( xlat_table, filename, remotefile )
- struct LPDxlat *xlat_table;
- char *filename, *remotefile;
- {
- char *strdup();
- int index;
-
- #ifdef LPD_DEBUG
- tprintf( "enter_translation( %s, %s )\n", filename, remotefile );
- tflush();
- #endif
-
- for( index = 0; index < 32; index++ ) {
- if( xlat_table->xlat[ index ].dfname == NULL ) {
- /* found an empty slot */
- xlat_table->xlat[ index ].dfname = strdup( remotefile );
- xlat_table->xlat[ index ].dos_dfname = strdup( filename );
- return;
- }
- }
- YIELD;
- }
-
- static int
- fixup_and_write_control_file( LPD, filename )
- struct LPDtrans *LPD;
- char *filename;
- {
- char *ptr, *strchr(), old_filename[128], *optr;
- int index;
- FILE *fp;
-
- #ifdef LPD_DEBUG
- tprintf( "fixup_and_write_control_file( %s )\n", filename );
- tflush();
- #endif
-
- fp = fopen( filename, WRITE_TEXT );
-
- ptr = LPD->cf_data;
- while( *ptr ) {
- if( *ptr > 'a' && *ptr <'z' || *ptr == 'U' ) {
- /* translation needed */
-
- putc( *ptr++, fp );
- optr = old_filename;
- while( *ptr && *ptr != '\n' )
- *optr++ = *ptr++;
- *optr = NULL;
- for( index = 0; index < 32; index++ ) {
- if( strcmp( LPD->xlat_table->xlat[ index ].dfname, old_filename ) == 0 ) {
- /* found the translation */
- fputs( LPD->xlat_table->xlat[ index ].dos_dfname, fp );
- break;
- }
- }
- }
- while( *ptr && *ptr != '\n' )
- putc( *ptr++, fp );
- if( *ptr == NULL )
- break;
- putc( *ptr++, fp ); /* output linefeed */
- YIELD;
- }
- fclose( fp );
- free( LPD->cf_data );
-
- /*
- * Clean up translations
- */
- for( index = 0; index < 32; index++ ) {
- if( LPD->xlat_table->xlat[ index ].dfname != NULL ) {
- /* clean slot */
- free( LPD->xlat_table->xlat[ index ].dfname );
- free( LPD->xlat_table->xlat[ index ].dos_dfname );
- LPD->xlat_table->xlat[ index ].dfname = NULL;
- }
- }
- YIELD;
- return 0;
- }
-
- static int
- validate_control_file( LPD, priority )
- struct LPDtrans *LPD;
- char *priority;
- {
- char *ptr, host[64], user[32], class[32];
- int index;
-
- #ifdef LPD_DEBUG
- tprintf( "validating control file\n" );
- tflush();
- #endif
-
- memset( host, 0, sizeof( host ) );
- memset( user, 0, sizeof( user ) );
- memset( class, 0, sizeof( class ) );
-
- /*
- * Extract info to test permissions
- */
- ptr = LPD->cf_data;
- while( *ptr ) {
- if( *ptr == 'H' ) { /* host name */
- index = 0;
- while( *++ptr && *ptr != '\n' )
- host[index++] = *ptr;
- host[index] = NULL;
- } else if( *ptr == 'P' ) { /* login name */
- index = 0;
- while( *++ptr && *ptr != '\n' )
- user[index++] = *ptr;
- user[index] = NULL;
- } else if( *ptr == 'C' ) { /* class or priority */
- index = 0;
- while( *++ptr && *ptr != '\n' )
- class[index++] = *ptr;
- class[index] = NULL;
- }
- while( *ptr && *ptr != '\n' )
- ptr++;
- if( *ptr++ == NULL )
- break;
- YIELD;
- }
- *priority = *class;
- if( priority == 0 )
- *priority = 'Z';
- if( !isascii( *priority ) || !isupper( *priority ) )
- *priority = 'Z';
-
- YIELD;
- if( secure && !check_permission( host, user, LPD->name, priority ) ) {
- /*
- * Setup log file
- */
- LPD->logfp = fopen( LPD->pc->LF, "a" );
- lpd_log( LPD, "lpd: permission rejected for %s, %s, %s, %c ", host, user, LPD->name, *priority );
- if( LPD->logfp )
- fclose( LPD->logfp );
- return -1;
- }
- YIELD;
- return 0;
- }
-
- int
- is_lpd_active(void)
- {
- return( (Slpd == -1) ? 0 : 1 );
- }
-
- static char *parms[ MAX_PARMS ];
- static int parms_count;
-
- char *
- extract_parms( local_parms, extra )
- char *local_parms;
- int extra;
- {
- char *cp, *skipp;
-
- cp = strtok( local_parms, " " ); /* skip <printer> */
- while( --extra > 0 )
- skipp = strtok( NULL, " " ); /* skip other unused parms */
-
- /*
- * Build parameter list
- */
- parms_count = 0;
- while( parms_count < MAX_PARMS && (cp = strtok( NULL, " " )) != NULL )
- parms[ parms_count++ ] = cp;
-
- return( skipp ); /* last skipped parameter */
- }
-
- int
- send_queue( LPD, type, local_parms )
- struct LPDtrans *LPD;
- int type;
- char *local_parms;
- {
- int active;
- unsigned int flags, next_seq, job_count, job;
- char *message, status[32], line[81];
- char *path, *active_job, *strdup();
- struct job_entry *job_list;
- struct stat fstatus;
- FILE *cfp;
-
- /* job specific info */
- char *owner, host[12], files[21], date[12], *suffix;
- long size;
-
- #ifdef LPD_DEBUG
- tprintf( "send_queue( %s, %d )\n", LPD->name, type );
- tflush();
- #endif
-
- (void)extract_parms( local_parms, 1 );
-
- active = is_unspooler_active( LPD->name, &active_job );
- job_count = get_job_list( LPD->pc->SD, &job_list );
-
- read_status( LPD->name, &flags, &next_seq, &message );
- *status = NULL;
- if( (flags & QUEUE_ENABLED) == 0 )
- strcat( status, "no spooling" );
- if( (flags & PRINT_ENABLED) == 0 ) {
- if( *status )
- strcat( status, ", " );
- strcat( status, "no printing" );
- }
-
- if( type == SQUEUE_CMD ) {
- usprintf( LPD->remote, "%s: %d jobs", LPD->name, job_count );
- if( *status )
- usprintf( LPD->remote, " (%s)", status );
- usputc( LPD->remote, '\n' );
- } else {
- usprintf( LPD->remote, "Printer '%s' (%s)", LPD->name, Hostname );
- if( LPD->pc->CM )
- usprintf( LPD->remote, " %s", LPD->pc->CM );
- usputc( LPD->remote, ':' );
- if( *status )
- usprintf( LPD->remote, " (%s)", status );
- usputc( LPD->remote, '\n' );
- if( job_count > 0 && !active )
- usputs( LPD->remote, "Warning: no unspooler present\n" );
- usprintf( LPD->remote, " %s\n", message );
- }
-
- if( job_count > 0 && type == QUEUE_CMD ) {
- usputs( LPD->remote, " Rank Owner Pr Job Host Files" );
- usputs( LPD->remote, " Size Date\n" );
- }
-
- /*
- * Read each control file for information and display
- */
- for( job = 0; job < job_count; job++ ) {
-
- if( !is_job_specified( job_list[ job ].j_name ) ) {
- free( job_list[ job ].j_name );
- continue;
- }
-
- size = 0;
- *host = NULL;
- *files = NULL;
-
- path = pathname( LPD->pc->SD, job_list[ job ].j_name );
-
- if( (cfp = fopen( path, "r" )) == NULL ) {
- free( path );
- continue;
- }
- stat( path, &fstatus );
- free( path );
-
- sprintf( date, "%7.7s%4.4s", ctime( &fstatus.st_mtime ) + 4,
- ctime( &fstatus.st_mtime ) + 20 );
-
- while( fgets( line, 80, cfp ) != NULL ) {
- rip( line );
- if( islower( *line ) ) {
- path = pathname( LPD->pc->SD, line+1 );
- if( stat( path, &fstatus ) != 0 ) {
- free( path );
- continue;
- }
- free( path );
- size += fstatus.st_size;
- } else if( *line == 'P' ) {
- owner = strdup( line+1 );
- } else if( *line == 'N' ) {
- if( *files )
- trunc_strcat( files, ",", 20 );
- trunc_strcat( files, line+1, 20 );
- } else if( *line == 'H' ) {
- trunc_strcat( host, line+1, 11 );
- }
- }
- fclose( cfp );
- if( type == SQUEUE_CMD ) { /* short form */
- usprintf( LPD->remote, "%d cf%s: %s\n", job+1, job_list[ job ].j_name+2, owner );
- } else { /* long form */
- if( strcmp( active_job, job_list[ job ].j_name ) == 0 ) {
- strcpy( line, "active" );
- } else {
- switch( job+1 ) {
- case 1: suffix = "st"; break;
- case 2: suffix = "nd"; break;
- case 3: suffix = "rd"; break;
- default: suffix = "th"; break;
- }
- sprintf( line, "%d%s", job+1, suffix );
- }
-
- usprintf( LPD->remote, "%6s %-11s %-c %-3s %-11s %-20s %-6ld %s\n",
- line, /* rank */
- owner, /* owner */
- job_list[ job ].j_name[2], /* priority */
- job_list[ job ].j_name + 4, /* job */
- host, /* host */
- files, /* files in job */
- size, /* job size */
- date /* date submitted */
- );
- }
- free( job_list[ job ].j_name );
-
- free( owner );
- }
- if( job_count > 0 )
- free( job_list );
- }
-
- int
- trunc_strcat( dest, source, max_length )
- char *dest, *source;
- int max_length;
- {
- strncat( dest, source, max_length - strlen( dest ) );
- }
-
- int
- is_job_specified( cf_name )
- char *cf_name;
- {
- int parm, job_spec, job_no;
-
- if( parms_count == 0 ) /* match all */
- return 1;
- for( parm = 0; parm < parms_count; parm++ ) {
- if( isdigit( *parms[ parm ] ) ) { /* job number specified */
-
- job_spec = atoi( parms[ parm ] );
- job_no = atoi( cf_name + 4 );
-
- if( job_spec == job_no )
- return 1;
- } /* user name - NOT SUPPORTED */
- }
- return 0;
- }
-
- static int
- get_owner( directory, cf_name, owner )
- char *directory, *cf_name, **owner;
- {
- char *path, line[81];
- FILE *cfp;
-
- *owner = NULL;
-
- path = pathname( directory, cf_name );
- if( (cfp = fopen( path, "r" )) == NULL ) {
- free( path );
- return -1;
- }
- free( path );
-
- while( fgets( line, 80, cfp ) != NULL ) {
- rip( line );
- if( *line == 'P' )
- *owner = strdup( line+1 );
- }
- fclose( cfp );
-
- return 0;
- }
-
- static int
- remove_files( directory, cf_name )
- char *directory, *cf_name;
- {
- char *path, line[81];
- FILE *cfp;
-
- path = pathname( directory, cf_name );
- if( (cfp = fopen( path, "r" )) == NULL ) {
- free( path );
- return -1;
- }
- free( path );
-
- while( fgets( line, 80, cfp ) != NULL ) {
- rip( line );
- if( *line == 'U' ) {
- path = pathname( directory, line+1 );
- remove( path );
- free( path );
- }
- }
- fclose( cfp );
-
- path = pathname( directory, cf_name );
- remove( path );
- free( path );
-
- return 0;
- }
-
- static int
- remove_job( LPD, local_parms )
- struct LPDtrans *LPD;
- char *local_parms; /* <printer> <user> <jobs> */
- {
- int all, active, job, job_count;
- char *user, *owner, *cp;
- char *active_job;
- struct job_entry *job_list;
-
- usprintf( LPD->remote, "Printer '%s' (%s):\n", LPD->name, Hostname );
-
- user = extract_parms( local_parms, 2 );
-
- active = is_unspooler_active( LPD->name, &active_job );
- job_count = get_job_list( LPD->pc->SD, &job_list );
-
- /*
- * Check each job against request
- */
- for( job = 0; job < job_count; job++ ) {
-
- if( get_owner( LPD->pc->SD, job_list[ job ].j_name, &owner ) < 0 )
- continue;
- if( strcmp( user, owner ) != 0 ) { /* not owner of job */
- free( owner );
- continue;
- }
-
- if( is_job_specified( job_list[ job ].j_name ) ) {
- usprintf( LPD->remote, "removing cf%s, job %-3s owner %s\n",
- job_list[ job ].j_name + 2,
- job_list[ job ].j_name + 3,
- owner );
-
- if( active && strcmp( job_list[ job ].j_name, active_job ) == 0 ) {
- /* unspooler is processing our job, kill it */
-
- usprintf( LPD->remote, "killing off %s unspooler\n", LPD->name );
-
- kill_unspooler( LPD->name );
- }
- remove_files( LPD->pc->SD, job_list[ job ].j_name );
- YIELD;
- }
- free( job_list[ job ].j_name );
- free( owner );
- }
- free( job_list );
-
- YIELD;
- return 0;
- }
-